package com.skt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.skt.domain.DTO.MerchantCostumeQueryDTO;
import com.skt.domain.DTO.request.MerchantCostumeCreateRequest;
import com.skt.domain.DTO.request.MerchantCostumeUpdateRequest;
import com.skt.domain.ENUM.AccountStatus;
import com.skt.domain.ENUM.UserRole;
import com.skt.domain.PO.Costume;
import com.skt.domain.PO.User;
import com.skt.domain.VO.MerchantCostumeCreateResultVO;
import com.skt.domain.VO.MerchantCostumeUpdateResultVO;
import com.skt.domain.VO.MerchantCostumeVO;
import com.skt.exception.*;
import com.skt.mapper.CostumeMapper;
import com.skt.mapper.UserMapper;
import com.skt.security.LoginUser;
import com.skt.service.MerchantCostumesService;
import com.skt.utils.LogUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantCostumesServiceImpl extends ServiceImpl<CostumeMapper, Costume> implements MerchantCostumesService {

    private final UserMapper userMapper;
    private final CostumeMapper costumeMapper;

    /**
     * 商家发布商品
     * @param createRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MerchantCostumeCreateResultVO createCostume(MerchantCostumeCreateRequest createRequest) {
        // 1. 用户身份验证
        Long merchantId = validateMerchantIdentity();

        // 2. 参数校验（Spring Validation已处理基础校验，这里做业务逻辑校验）
        validateBusinessParams(createRequest);

        // 3. 构建商品实体
        Costume costume = buildCostume(createRequest, merchantId);

        // 4. 持久化
        boolean saveResult = save(costume);
        if (!saveResult) {
            log.error("商家发布商品失败，商家ID：{}，商品名称：{}", merchantId, createRequest.getName());
            throw new RuntimeException("商品保存失败");
        }

        // 5. 构建返回结果
        return buildCreateResultVO(costume);
    }

    /**
     * 商家编辑商品
     * @param id
     * @param updateRequest
     * @return
     */
    @Override
    public MerchantCostumeUpdateResultVO updateCostume(Long id, MerchantCostumeUpdateRequest updateRequest) {
        // 1. 权限验证
        Long merchantId = validateCostumeEditable(id);

        // 2. 参数校验
        validateCostumeUpdateParams(updateRequest);

        // 3. 构建商品实体
        Costume costume = buildUpdateCostume(updateRequest, merchantId);

        // 4. 持久化
        boolean saveResult = save(costume);
        if (!saveResult) {
            LogUtil.error("COSTUME", "UPDATE", "商家编辑商品失败，商家ID：{}，商品名称：{}", merchantId, updateRequest.getName());
            throw new RuntimeException("商品编辑失败");
        }

        // 5.构建返回结果
        return buildUpdateResultVO(costume);
    }

    /**
     * 商家商品列表查询
     *
     * @param queryDTO@return
     */
    @Override
    public List<MerchantCostumeVO> listCostumes(MerchantCostumeQueryDTO queryDTO) {
        // 1. 权限校验：确保当前用户有权查询该商家商品
        Long merchantId = validateCostumeQueryable();

        // 2. 参数校验
        validateQueryParams(queryDTO);

        // 3. 构建分页对象
        Page<Costume> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        // 4. 构建查询条件
        LambdaQueryWrapper<Costume> wrapper = buildQueryCostume(queryDTO, merchantId);

        // 5. 执行查询
        costumeMapper.selectPage(page, wrapper);

        // 6. 转换为 VO 列表（直接映射，status 值保持 0~4 不变）
        return page.getRecords().stream()
                .map(costume -> new MerchantCostumeVO()
                        .setId(costume.getId())
                        .setMerchantId(costume.getMerchantId())
                        .setName(costume.getName())
                        .setCategory(costume.getCategory())
                        .setSize(costume.getSize())
                        .setColor(costume.getColor())
                        .setBrand(costume.getBrand())
                        .setPurchaseDate(costume.getPurchaseDate())
                        .setPrice(costume.getPrice())
                        .setRentalPrice(costume.getRentalPrice())
                        .setStatus(costume.getStatus()) // 直接返回 0~4 的状态值
                        .setDescription(costume.getDescription())
                        .setImageUrl(costume.getImageUrl())
                        .setCreatedAt(costume.getCreatedAt())
                        .setUpdatedAt(costume.getUpdatedAt())
                )
                .collect(Collectors.toList());
    }

    /**
     * 参数校验
     */
    private void validateQueryParams(MerchantCostumeQueryDTO queryDTO) {
        // 校验分页参数
        if (queryDTO.getPageNum() == null || queryDTO.getPageNum() < 1) {
            throw CostumeException.of(CostumeErrorCode.PAGE_NUMBER_INVALID);
        }
        if (queryDTO.getPageSize() == null || queryDTO.getPageSize() < 1 || queryDTO.getPageSize() > 100) {
            throw CostumeException.of(CostumeErrorCode.PAGE_SIZE_INVALID);
        }

        // 校验 status 范围：必须是 0~4
        if (queryDTO.getStatus() != null) {
            int status = queryDTO.getStatus();
            if (status < 0 || status > 4) {
                throw CostumeException.of(CostumeErrorCode.MERCHANT_COSTUME_STATUS_FILTER_INVALID, "商品状态值无效，应为 0-4");
            }
        }

        // 校验排序字段
        Set<String> allowedSortFields = Set.of("createTime", "rentalPrice", "stock");
        if (queryDTO.getSortField() != null && !allowedSortFields.contains(queryDTO.getSortField())) {
            throw CostumeException.of(CostumeErrorCode.MERCHANT_COSTUME_SORT_FIELD_INVALID, "不支持的排序字段");
        }

        // 校验排序方向
        if (queryDTO.getSortOrder() != null) {
            String order = queryDTO.getSortOrder().trim();
            if (!"asc".equalsIgnoreCase(order) && !"desc".equalsIgnoreCase(order)) {
                throw CostumeException.of(CostumeErrorCode.INVALID_SORT_ORDER, "排序方向只能是 asc 或 desc");
            }
        }
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<Costume> buildQueryCostume(MerchantCostumeQueryDTO queryDTO, Long merchantId) {
        LambdaQueryWrapper<Costume> query = Wrappers.lambdaQuery(Costume.class)
                .eq(Costume::getMerchantId, merchantId); // 数据隔离

        // 状态筛选（0~4，直接匹配）
        if (queryDTO.getStatus() != null) {
            query.eq(Costume::getStatus, queryDTO.getStatus().byteValue());
        }

        // 分类筛选（假设 PO.category 存的是 categoryId.toString()）
        if (queryDTO.getCategoryId() != null) {
            query.eq(Costume::getCategory, queryDTO.getCategoryId().toString());
        }

        // 关键词模糊搜索（按名称）
        if (StringUtils.hasText(queryDTO.getKeyword())) {
            query.like(Costume::getName, queryDTO.getKeyword());
        }

        // 排序处理
        String sortField = StringUtils.hasText(queryDTO.getSortField()) ? queryDTO.getSortField() : "createTime";
        String sortOrder = StringUtils.hasText(queryDTO.getSortOrder()) ? queryDTO.getSortOrder() : "desc";

        boolean isAsc = "asc".equalsIgnoreCase(sortOrder);

        switch (sortField) {
            case "createTime" -> {
                if (isAsc) query.orderByAsc(Costume::getCreatedAt);
                else query.orderByDesc(Costume::getCreatedAt);
            }
            case "rentalPrice" -> {
                if (isAsc) query.orderByAsc(Costume::getRentalPrice);
                else query.orderByDesc(Costume::getRentalPrice);
            }
            case "stock" -> {
                if (isAsc) query.orderByAsc(Costume::getStock);
                else query.orderByDesc(Costume::getStock);
            }
            default -> query.orderByDesc(Costume::getCreatedAt);
        }

        return query;
    }

    /**
     * 权限验证
     */
    private Long validateCostumeQueryable() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw AuthException.of(AuthErrorCode.TOKEN_INVALID, "Token无效或已过期");
        }

        Object principal = authentication.getPrincipal();
        Long merchantId = null;
        if (principal instanceof LoginUser loginUser) {
            merchantId = loginUser.getUserId();
        }

        if (merchantId == null) {
            throw AuthException.of(AuthErrorCode.USER_NOT_EXIST, "商家ID为空");
        }

        User user = userMapper.selectById(merchantId);

        if (user == null) {
            throw AuthException.of(AuthErrorCode.USER_NOT_EXIST, "商家不存在");
        }

        if (user.getAccountStatus() != AccountStatus.ENABLED) {
            throw AuthException.of(AuthErrorCode.ACCOUNT_DISABLED, "账户已被禁用");
        }

        if (user.getRole() != UserRole.MERCHANT) {
            throw AuthException.of(AuthErrorCode.PERMISSION_DENIED, "用户不是商家");
        }

        return merchantId;
    }

    /**
     * 构建更新商品的返回结果
     * @param costume
     * @return
     */
    private MerchantCostumeUpdateResultVO buildUpdateResultVO(
            Costume costume) {

        MerchantCostumeUpdateResultVO resultVO = new MerchantCostumeUpdateResultVO();
        resultVO.setCostumeId(costume.getId());
        resultVO.setNewStatus(costume.getStatus());

        resultVO.setUpdateTime(costume.getUpdatedAt() != null
                ? costume.getUpdatedAt()
                : LocalDateTime.now());

        return resultVO;
    }

    /**
     * 构建更新商品实体
     * @param updateRequest
     * @param merchantId
     */
    private Costume buildUpdateCostume(MerchantCostumeUpdateRequest updateRequest, Long merchantId) {
        Costume costume = new Costume();

        // 复制基本属性
        costume.setMerchantId(merchantId)
                .setName(updateRequest.getName())
                .setCategory(updateRequest.getCategory())
                .setSize(updateRequest.getSize())
                .setColor(updateRequest.getColor())
                .setBrand(updateRequest.getBrand())
                .setPurchaseDate(updateRequest.getPurchaseDate())
                .setPrice(updateRequest.getPrice())
                .setRentalPrice(updateRequest.getRentalPrice())
                .setDescription(updateRequest.getDescription())
                .setImageUrl(updateRequest.getImageUrl());

        costume.setStatus((byte) 0); // 等待审核

        return costume;
    }

    /**
     * 校验服装更新参数
     * @param updateRequest
     */
    private void validateCostumeUpdateParams(MerchantCostumeUpdateRequest updateRequest) {
        // 图片URL长度校验（虽然DTO有校验，这里再做一次业务逻辑校验）
        if (updateRequest.getImageUrl() != null && updateRequest.getImageUrl().length() > 255) {
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "图片URL长度不能超过255个字符");
        }

        // 日租金和购入价格比较（业务规则：日租金应该小于购入价格）
        if (updateRequest.getPrice() != null && updateRequest.getRentalPrice() != null) {
            if (updateRequest.getRentalPrice().compareTo(updateRequest.getPrice()) >= 0) {
                throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "日租金应小于购入价格");
            }
        }

        // 购入日期不能晚于当前日期
        if (updateRequest.getPurchaseDate() != null && updateRequest.getPurchaseDate().isAfter(java.time.LocalDate.now())) {
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "购入日期不能晚于当前日期");
        }
    }

    /**
     * 验证服装是否可以进行编辑
     * @param id
     */
    private Long validateCostumeEditable(Long id) {
        // 验证商家状态
        Long merchantId = validateMerchantIdentity();

        User merchant = userMapper.selectById(merchantId);

        if (merchant.getAccountStatus() != AccountStatus.ENABLED) {
            throw AuthException.of(AuthErrorCode.ACCOUNT_LOCKED, "账户已被禁用");
        }

        if (merchant.getRole() != UserRole.MERCHANT) {
            throw AuthException.of(AuthErrorCode.PERMISSION_DENIED, "权限不足");
        }

        // 验证商品状态
        Costume costume = costumeMapper.selectById(id);

        if (!costume.getMerchantId().equals(merchantId)) {
            throw CostumeException.of(CostumeErrorCode.COSTUME_ACCESS_DENIED, "无权访问该商品");
        }

        if (costume.getStatus() != 1) {
            throw CostumeException.of(CostumeErrorCode.COSTUME_UNDER_MAINTENANCE, "商品维护中");
        }

        return merchantId;
    }

    /**
     * 构建商品实体
     */
    private Costume buildCostume(MerchantCostumeCreateRequest createRequest, Long merchantId) {
        Costume costume = new Costume();

        // 复制基本属性
        costume.setMerchantId(merchantId)
                .setName(createRequest.getName())
                .setCategory(createRequest.getCategoryId().toString()) // 注意：PO中是String类型，DTO中是Long
                .setSize(createRequest.getSize())
                .setStock(createRequest.getStock())
                .setColor(createRequest.getColor())
                .setBrand(createRequest.getBrand())
                .setPurchaseDate(createRequest.getPurchaseDate())
                .setPrice(createRequest.getPrice())
                .setRentalPrice(createRequest.getRentalPrice())
                .setDescription(createRequest.getDescription())
                .setImageUrl(createRequest.getImageUrl());


        costume.setStatus((byte) 0); // 等待审核

        // 时间字段由MyBatis Plus自动填充
        return costume;
    }

    /**
     * 构建创建结果VO
     */
    private MerchantCostumeCreateResultVO buildCreateResultVO(Costume costume) {
        MerchantCostumeCreateResultVO resultVO = new MerchantCostumeCreateResultVO();
        resultVO.setCostumeId(costume.getId());
        resultVO.setCostumeName(costume.getName());
        resultVO.setStatus(0); // 新创建的商品状态为待审核
        resultVO.setStatusDesc("待审核");
        resultVO.setCreateTime(costume.getCreatedAt() != null ? costume.getCreatedAt() : LocalDateTime.now());
        resultVO.setExpectAuditTime(LocalDateTime.now().plusHours(24));
        resultVO.setNextStepGuide("商品已提交审核，请耐心等待平台审核结果");

        return resultVO;
    }

    /**
     * 业务参数校验（Spring Validation已处理基础校验）
     * @param createRequest
     */
    private void validateBusinessParams(MerchantCostumeCreateRequest createRequest) {
        // 图片URL长度校验（虽然DTO有校验，这里再做一次业务逻辑校验）
        if (createRequest.getImageUrl() != null && createRequest.getImageUrl().length() > 255) {
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "图片URL长度不能超过255个字符");
        }

        // 日租金和购入价格比较（业务规则：日租金应该小于购入价格）
        if (createRequest.getPrice() != null && createRequest.getRentalPrice() != null) {
            if (createRequest.getRentalPrice().compareTo(createRequest.getPrice()) >= 0) {
                throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "日租金应小于购入价格");
            }
        }

        // 购入日期不能晚于当前日期
        if (createRequest.getPurchaseDate() != null && createRequest.getPurchaseDate().isAfter(java.time.LocalDate.now())) {
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "购入日期不能晚于当前日期");
        }

        // 库存为0时给出警告日志（但不阻止创建）
        if (createRequest.getStock() != null && createRequest.getStock() == 0) {
            log.warn("创建商品时库存为0，商品名称：{}", createRequest.getName());
        }
    }

    /**
     * 验证商家身份
     */
    private Long validateMerchantIdentity() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw AuthException.of(AuthErrorCode.TOKEN_INVALID, "Token无效或已过期");
        }

        Object principal = authentication.getPrincipal();
        Long merchantId = null;
        if (principal instanceof LoginUser loginUser) {
            merchantId = loginUser.getUserId();
        }

        if (merchantId == null) {
            throw AuthException.of(AuthErrorCode.USER_NOT_EXIST, "商家ID为空");
        }

        User user = userMapper.selectById(merchantId);
        if (user == null) {
            throw AuthException.of(AuthErrorCode.USER_NOT_EXIST, "用户不存在");
        }

        if (user.getAccountStatus() != AccountStatus.ENABLED) {
            throw AuthException.of(AuthErrorCode.ACCOUNT_DISABLED, "账号已被禁用");
        }

        if (user.getRole() != UserRole.MERCHANT) {
            throw AuthException.of(AuthErrorCode.PERMISSION_DENIED, "用户不是商家");
        }

        return merchantId;
    }
}